package services;

import java.util.Collection;
import java.util.HashSet;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import repositories.PaintingRepository;
import domain.Administrator;
import domain.Auction;
import domain.Comment;
import domain.Customer;
import domain.Gallery;
import domain.OwnershipHistory;
import domain.Painting;
import forms.PaintingForm;

@Service
@Transactional
public class PaintingService {

	// Managed Repository
	@Autowired
	private PaintingRepository paintingRepository;

	// Supporting Services
	@Autowired
	private CustomerService customerService;
	@Autowired
	private AuctionService auctionService;
	@Autowired
	private OwnershipHistoryService ownershipHistoryService;
	@Autowired
	private AdministratorService administratorService;

	// Constructor Method
	public PaintingService() {
		super();
	}

	// Simple Crud Methods

	public Painting create() {
		Painting result;
		Customer customer;
		Collection<Auction> auctions;
		Collection<Comment> comments;
		Collection<OwnershipHistory> ownershipHistories;

		customer = customerService.findByPrincipal();

		result = new Painting();

		auctions = new HashSet<Auction>();
		comments = new HashSet<Comment>();
		ownershipHistories = new HashSet<OwnershipHistory>();

		result.setCustomer(customer);
		result.setGallery(null);

		result.setAuctions(auctions);
		result.setComments(comments);
		result.setOwnershipHistories(ownershipHistories);

		return result;
	}

	public void save(Painting p) {
		Assert.notNull(p);
		Assert.isTrue(noActiveAuctions(p));
		Assert.isTrue(p.getCustomer().equals(customerService.findByPrincipal()));

		OwnershipHistory oh;
		Painting savedPainting;

		savedPainting = paintingRepository.save(p);
		if (p.getId() == 0) {
			oh = ownershipHistoryService.create(savedPainting);
			ownershipHistoryService.save(oh);
		}
	}

	public Collection<Painting> findAll() {
		Collection<Painting> result;

		result = paintingRepository.findAll();

		return result;
	}

	public Painting findOne(int paintingId) {
		Painting result;

		result = paintingRepository.findOne(paintingId);

		return result;
	}

	// Other Business Methods

	public Collection<Painting> findByCustomer(Customer c) {
		Collection<Painting> result;

		result = paintingRepository.findByCustomer(c.getId());

		return result;
	}

	public Collection<Painting> findByGallery(Gallery g) {
		Collection<Painting> result;

		result = paintingRepository.findByGallery(g.getId());

		return result;
	}

	public Collection<Painting> findOwnedPaintings() {
		Collection<Painting> result;

		result = paintingRepository.findOwnedPaintings(customerService
				.findByPrincipal().getId());

		return result;
	}
	
	public Collection<Painting> findOwnedPaintingsByCustomerId(int customerId) {
		Collection<Painting> result;

		result = paintingRepository.findOwnedPaintings(customerId);

		return result;
	}

	public Collection<Painting> findByMoreComments() {
		Collection<Painting> res;
		Administrator principal;
		principal = administratorService.findByPrincipal();
		Assert.isTrue(principal instanceof Administrator);
		res = paintingRepository.findByMoreComments();
		return res;
	}

	public Boolean noActiveAuctions(Painting painting) {
		Boolean result;

		result = auctionService.findActiveAuctionsByPainting(painting)
				.isEmpty();

		return result;
	}

	public Boolean noPendingAuctions(Painting painting) {
		Boolean result;

		result = auctionService.findPendingAuctionByPainting(painting) == null;

		return result;
	}

	// Form methods

	public PaintingForm createForm() {
		PaintingForm paintingForm;

		paintingForm = new PaintingForm();

		paintingForm.setPaintingId(0);
		paintingForm.setGallery(null);

		return paintingForm;
	}

	public PaintingForm paintingToForm(Painting p) {
		Assert.notNull(p);
		PaintingForm result;

		result = new PaintingForm();

		result.setPaintingId(p.getId());
		result.setTitle(p.getTitle());
		result.setAuthor(p.getAuthor());
		result.setAppraisal(p.getAppraisal());
		result.setDate(p.getDate());
		result.setGallery(p.getGallery());

		return result;
	}

	public Painting reconstruct(PaintingForm pf) {
		Assert.notNull(pf);
		Painting result;

		if (pf.getPaintingId() == 0) {
			result = create();

			result.setTitle(pf.getTitle());
			result.setAuthor(pf.getAuthor());
			result.setAppraisal(pf.getAppraisal());
			result.setDate(pf.getDate());

			result.setGallery(null);
		} else {
			result = findOne(pf.getPaintingId());
			Assert.notNull(result);

			result.setTitle(pf.getTitle());
			result.setAuthor(pf.getAuthor());
			result.setAppraisal(pf.getAppraisal());
			result.setDate(pf.getDate());
			result.setGallery(pf.getGallery());
		}

		return result;

	}

}
